﻿/**
 *	(C) 2014 Yuanjj
 *
 *	define data base protocal thread class
 *
 *	histroy
 * 		2014-08-07	yuanjj	- create the file
 */

#include "db_thread.h"
#include "errorcode.h"
#include "routine/global.h"
#include "routine/protocal/db_protocal.h"
#include "routine/protocal/ui_protocal.h"
#include <QMessageBox>

db_thread::db_thread()
{
    m_tunnel	= CL_DB;
    m_main		= MAIN_DB;
}

db_thread::~db_thread()
{
}

/**
 *	deal protocal recv from the db tunnel
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t	db_thread::deal_protocal( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t		res;
    head_in&		head = *(head_in*)pdata;

    res = base_thread::deal_protocal( pdata, size );
    if ( PEM_OK != res ) return res;

    switch ( head.second )
    {
    case DB_USER_LOGIN:
        res = _user_login( pdata, size ); break;
    case DB_HOST:
        res = _load_host( pdata, size ); break;
    case DB_TUNNEL_TYPE:
        res = _load_tunnel_type( pdata, size ); break;
    case DB_TUNNEL:
        res = _load_tunnel( pdata, size ); break;
    case DB_TUNNEL_UPDATE:
        res = _update_tunnel( pdata, size ); break;
    case DB_TUNNEL_DELETE:
        res = _delete_tunnel( pdata, size ); break;
    case DB_DEV_TYPE:
        res = _load_device_type( pdata, size ); break;
    case DB_DEVICE:
        res = _load_device( pdata, size ); break;
    case DB_DEVICE_UPDATE:
        res = _update_device( pdata, size ); break;
    case DB_PROTOCAL:
        res = _load_protocal( pdata, size ); break;
    case DB_ALARM:
        res = _load_alarm( pdata, size ); break;
    case DB_EVENT_TYPE:
        res = _load_event_type( pdata, size ); break;
    case DB_EVENT:
        res = _load_event( pdata, size ); break;
    case DB_SCENE:
        res = _load_scene( pdata, size ); break;
    case DB_SCENE_SAVE:
        res = _save_scene( pdata, size ); break;
    case DB_FRAME:
        res = _load_frame( pdata, size ); break;
    default:
        res = BUILD_ERRORCODE( 0, PEM_PROTOCAL_UNKNOW );
        g_log.write( LOG_WARN, "db thread", "Unknow protocal second(%d)", head.second );
        break;
    }

    return	res;
}

/**
 *	user login
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_user_login( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t	res = PEM_OK;

    g_db.lock();

    res = __user_login( pdata, size );

    g_db.unlock();

    return	res;
}

pem_error_t	db_thread::__user_login( pem_s8_t* pdata, pem_u32_t size )
{
    pem_s8_t			buf[8192];
    pem_error_t			res 		= PEM_OK;
    head_in&			head		= *(head_in*)buf;
    ui_user_login*		uilogin		= (ui_user_login*)(&head + 1);
    db_user_login*		dblogin		= (db_user_login*)(pdata + sizeof(head_in));
    QByteArray			ba;
    QString				sql;
    cls_res				sqlres;

    memset( uilogin, 0, sizeof(ui_user_login) );

    do
    {
        // select user info
        sql.sprintf( "select * from tab_user where account = \"%s\" and passwd = \"%s\"", dblogin->account, dblogin->passwd );
        ba	= sql.toLatin1();
        res = g_db.query( ba.data() );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_ERR, "db thread", "user login failed[error = 0x%x, %sj]", res, g_db.get_error() );
            uilogin->status = 0x101;
            break;
        }

        res = g_db.get_res( sqlres );
        if ( PEM_OK != res )
        {
            uilogin->status	= 0x102;
            g_log.write( LOG_ERR, "db thread", "user login get result failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        // we only fetch one user (and the result, if it exists, has only one record)
        if ( !sqlres.get_next_row() )
        {
            uilogin->status	= 0x103;
            break;
        }

        // fetch user info
        sqlres.get_data_string( 0, uilogin->account, sizeof(uilogin->account) );
        uilogin->privilege 	= sqlres.get_data_int( 2 );
        uilogin->status		= sqlres.get_data_int( 5 );
        sqlres.free_res();

        // update user login date time
        sql.sprintf( "update tab_user set login = now() where account = \"%s\"", dblogin->account );
        ba 	= sql.toLatin1();
        res = g_db.query( ba.data() );
        if ( PEM_OK != res )
        {
            uilogin->status = 0x104;
            g_log.write( LOG_ERR, "db thread", "update user login datetime failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }
    } while( 0 );

    sqlres.free_res();

    FILL_HEAD( head, MAIN_UI, UI_USER_LOGIN, EN_NONE, sizeof(ui_user_login));
    g_tunnel.putdata( CL_UI, buf, sizeof(head_in) + head.size );

    return res;
}

/**
 *	load host from data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_load_host( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t			res	= PEM_OK;
    cls_res				sqlres;

    g_db.lock();

    do
    {
        res = g_db.query( "select serial, host, name, ip, port, status from tab_host order by serial asc" );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "load host failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = g_db.get_res( sqlres );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_ERR, "db thread", "get host result failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = __load_host( sqlres );
    } while ( 0 );
    sqlres.free_res();

    g_db.unlock();

    return	res;
}

/**
 *	load host
 *
 * 	@sqlres			[in] the sql result object
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::__load_host( cls_res& sqlres )
{
    pem_s8_t		buf[8192];
    pem_s32_t		index;
    head_in&		head 		= *(head_in*)buf;
    ui_host*		host		= (ui_host*)(&head + 1);

    FILL_HEAD( head, MAIN_UI, UI_HOST, EN_NONE, 0 );

    while ( sqlres.get_next_row() )
    {
        index = 0;
        host->serial	= sqlres.get_data_int( index++ );
        sqlres.get_data_string( index++, host->host, sizeof(host->host) );
        sqlres.get_data_string( index++, host->name, sizeof(host->name) );
        sqlres.get_data_string( index++, host->ip, sizeof(host->ip) );
        host->port		= sqlres.get_data_int( index++ );
        host->status	= sqlres.get_data_int( index++ );
        head.size 		+= sizeof(ui_host);
        host++;

        if ( (head.size + sizeof(head_in)) > (sizeof(buf) - sizeof(ui_host)) )
        {
            g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );
            head.size		= 0;
            host			= (ui_host*)(&head + 1);
        }
    }

    if ( head.size > 0 )
        g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );

    return	PEM_OK;
}

/**
 *	load tunnel type from data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_load_tunnel_type( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t			res	= PEM_OK;
    cls_res				sqlres;

    g_db.lock();

    do
    {
        res = g_db.query( "select serial, type from tab_tunnel_type order by serial asc" );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "load tunnel type failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = g_db.get_res( sqlres );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_ERR, "db thread", "get tunnel type result failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = __load_tunnel_type( sqlres );
    } while ( 0 );
    sqlres.free_res();

    g_db.unlock();

    return	res;
}

/**
 *	load tunnel type
 *
 * 	@sqlres			[in] the sql result object
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::__load_tunnel_type( cls_res& sqlres )
{
    pem_s8_t			buf[8192];
    pem_s32_t			index;
    head_in&			head 			= *(head_in*)buf;
    ui_tunnel_type*		tunnel_type		= (ui_tunnel_type*)(&head + 1);

    FILL_HEAD( head, MAIN_UI, UI_TUNNEL_TYPE, EN_NONE, 0 );

    while ( sqlres.get_next_row() )
    {
        index = 0;
        tunnel_type->serial = sqlres.get_data_int( index++ );
        sqlres.get_data_string( index++, tunnel_type->type, sizeof(tunnel_type->type) );
        head.size += sizeof(ui_tunnel_type);
        tunnel_type++;

        if ( (head.size + sizeof(head_in)) > (sizeof(buf) - sizeof(ui_tunnel_type)) )
        {
            g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );
            head.size		= 0;
            tunnel_type		= (ui_tunnel_type*)(&head + 1);
        }
    }

    if ( head.size > 0 )
        g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );

    return	PEM_OK;
}

/**
 *	load tunnel form data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_load_tunnel( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t			res	= PEM_OK;
    cls_res				sqlres;

    g_db.lock();

    do
    {
        res = g_db.query( "select host, number, name, type, remark, used from tab_tunnel order by host asc" );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "load tunnel failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = g_db.get_res( sqlres );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_ERR, "db thread", "get tunnel result failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = __load_tunnel( sqlres );
    }while( 0 );

    sqlres.free_res();

    g_db.unlock();

    return	res;
}

/**
 *	load tunnel
 *
 * 	@sqlres			[in] the sql result object
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::__load_tunnel( cls_res& sqlres )
{
    pem_s8_t			buf[8192];
    pem_s32_t			index;
    head_in&			head 		= *(head_in*)buf;
    ui_tunnel*			tunnel		= (ui_tunnel*)(&head + 1);

    FILL_HEAD( head, MAIN_UI, UI_TUNNEL, EN_NONE, 0 );

    while ( sqlres.get_next_row() )
    {
        index = 0;
        sqlres.get_data_string( index++, tunnel->host, sizeof(tunnel->host) );
        sqlres.get_data_string( index++, tunnel->number, sizeof(tunnel->number) );
        sqlres.get_data_string( index++, tunnel->name, sizeof(tunnel->name) );
        sqlres.get_data_string( index++, tunnel->type, sizeof(tunnel->type) );
        sqlres.get_data_string( index++, tunnel->remark, sizeof(tunnel->remark) );
        tunnel->used	= sqlres.get_data_int( index++ );

        head.size 		+= sizeof(ui_tunnel);
        tunnel++;

        if ( (head.size + sizeof(head_in)) > (sizeof(buf) - sizeof(ui_tunnel)) )
        {
            g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );
            head.size		= 0;
            tunnel			= (ui_tunnel*)(&head + 1);
        }
    }

    if ( head.size > 0 )
        g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );

    return	PEM_OK;
}

/**
 *	update device info to data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_update_tunnel( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t			res			= PEM_OK;
    head_in&			head 		= *(head_in*)pdata;
    db_tunnel_update*	tunnel		= (db_tunnel_update*)(&head + 1);
    QByteArray			ba;
    QString				sql;

    sql.sprintf( "insert into tab_tunnel"
                    "(name, type, number, host, remark, used)"
                    "values( \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", %d )"
                    "on duplicate key update "
                    " name = \"%s\", type = \"%s\", host = \"%s\", remark = \"%s\", used = %d",
                    tunnel->name, tunnel->type, tunnel->number, tunnel->host, tunnel->remark, tunnel->used,
                    tunnel->name, tunnel->type, tunnel->host, tunnel->remark, tunnel->used );
    ba = sql.toUtf8();

    g_db.lock();

    do{
        res = g_db.query( ba.data() );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "update tunnel failed[errorno = 0x%x, %s]", res, g_db.get_error() );
            break;
        }
    } while( 0 );

    g_db.unlock();

    return 	res;
}

/**
 *	delete tunnel info from data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_delete_tunnel( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t			res			= PEM_OK;
    head_in&			head 		= *(head_in*)pdata;
    db_tunnel_delete*	tunnel		= (db_tunnel_delete*)(&head + 1);
    QByteArray			ba;
    QString				sql;

    sql.sprintf( "delete from tab_tunnel where host = \"%s\" and number = \"%s\"", tunnel->host, tunnel->number );
    ba = sql.toUtf8();

    g_db.lock();

    do{
        res = g_db.query( ba.data() );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "delete tunnel failed[errorno = 0x%x, %s]", res, g_db.get_error() );
            break;
        }
    } while( 0 );

    g_db.unlock();

    return 	res;
}

/**
 *	load device type from data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_load_device_type( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t		res	= PEM_OK;
    cls_res			sqlres;

    g_db.lock();

    do
    {
        res = g_db.query( "select serial, type, name, probe, img, append from tab_device_type order by serial asc" );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "load device type failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = g_db.get_res( sqlres );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_ERR, "db thread", "get device type result failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = __load_device_type( sqlres );
    }while( 0 );

    sqlres.free_res();

    g_db.unlock();

    return	res;
}

/**
 *	load device type
 *
 * 	@sqlres			[in] the sql result object
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::__load_device_type( cls_res& sqlres )
{
    pem_s8_t		buf[8192];
    pem_s32_t		index;
    head_in&		head 		= *(head_in*)buf;
    ui_dev_type*	dev_type	= (ui_dev_type*)(&head + 1);

    FILL_HEAD( head, MAIN_UI, UI_DEV_TYPE, EN_NONE, 0 );

    while ( sqlres.get_next_row() )
    {
        index = 0;
        dev_type->serial = sqlres.get_data_int( index++ );
        sqlres.get_data_string( index++, dev_type->type, sizeof(dev_type->type) );
        sqlres.get_data_string( index++, dev_type->name, sizeof(dev_type->name) );
        sqlres.get_data_string( index++, dev_type->probe, sizeof(dev_type->probe) );
        sqlres.get_data_string( index++, dev_type->img, sizeof(dev_type->img) );
        sqlres.get_data_string( index++, dev_type->append, sizeof(dev_type->append) );
        head.size += sizeof(ui_dev_type);
        dev_type++;

        if ( (head.size + sizeof(head_in)) > (sizeof(buf) - sizeof(ui_dev_type)) )
        {
            g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );
            head.size	= 0;
            dev_type	= (ui_dev_type*)(&head + 1);
        }
    }

    if ( head.size > 0 )
        g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );

    return	PEM_OK;
}

/**
 *	load device from data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_load_device( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t		res	= PEM_OK;
    cls_res			sqlres;

    g_db.lock();

    do
    {
        res = g_db.query( "select host, dev_id, dev_type, dev_name, dev_pos, add_time, "
                          "machine, tunnel_num, pto_name, value, x, y, setup from tab_device" );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "load device failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = g_db.get_res( sqlres );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_ERR, "db thread", "get device result failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = __load_device( sqlres );
    }while( 0 );

    sqlres.free_res();

    g_db.unlock();

    return	res;
}

/**
 *	load device type
 *
 * 	@sqlres			[in] the sql result object
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::__load_device( cls_res& sqlres )
{
    pem_s8_t		buf[8192];
    pem_s32_t		index		= 0;
    head_in&		head 		= *(head_in*)buf;
    ui_device*		device		= (ui_device*)(&head + 1);

    FILL_HEAD( head, MAIN_UI, UI_DEVICE, EN_NONE, 0 );

    while ( sqlres.get_next_row() )
    {
        index = 0;
        sqlres.get_data_string( index++, device->host, sizeof(device->host) );
        sqlres.get_data_string( index++, device->dev_id, sizeof(device->dev_id) );
        sqlres.get_data_string( index++, device->dev_type, sizeof(device->dev_type) );
        sqlres.get_data_string( index++, device->dev_name, sizeof(device->dev_name) );
        sqlres.get_data_string( index++, device->dev_pos, sizeof(device->dev_pos) );
        sqlres.get_data_string( index++, device->add_time, sizeof(device->add_time) );
        sqlres.get_data_string( index++, device->machine, sizeof(device->machine) );
        sqlres.get_data_string( index++, device->tunnel_num, sizeof(device->tunnel_num) );
        sqlres.get_data_string( index++, device->pto_name, sizeof(device->pto_name) );
        sqlres.get_data_string( index++, device->value, sizeof(device->value) );
        device->x		= sqlres.get_data_int( index++ );
        device->y		= sqlres.get_data_int( index++ );
        device->setup	= sqlres.get_data_int( index++ );

        head.size 		+= sizeof(ui_device);
        device++;

        if ( (head.size + sizeof(head_in)) > (sizeof(buf) - sizeof(ui_device)) )
        {
            g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );
            head.size	= 0;
            device	= (ui_device*)(&head + 1);
        }
    }

    if ( head.size > 0 )
        g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );

    return	PEM_OK;
}

/**
 *	update device info to data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_update_device( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t			res			= PEM_OK;
    pem_s32_t			index		= 0;
    head_in&			head 		= *(head_in*)pdata;
    db_device_update*	device		= (db_device_update*)(&head + 1);
    QByteArray			ba;
    QString				sql;

    sql.sprintf( "insert into tab_device"
                    "(dev_id, dev_type, dev_name, dev_pos, add_time, machine, tunnel_num, pto_name, host, value, x, y, setup)"
                    "values( \"%s\", \"%s\", \"%s\", \"%s\", now(), \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", %d, %d, %d)"
                    "on duplicate key update "
                    " dev_type = \"%s\", dev_name = \"%s\", dev_pos = \"%s\","
                    " machine = \"%s\", tunnel_num = \"%s\", pto_name = \"%s\", value = \"%s\","
                    " x = %d, y = %d, setup = %d",
                    device->dev_id, device->dev_type, device->dev_name, device->dev_pos, device->machine, device->tunnel_num,
                    device->pto_name, device->host, device->value, device->x, device->y, device->setup,
                    device->dev_type, device->dev_name, device->dev_pos, device->machine, device->tunnel_num,
                    device->pto_name, device->value, device->x, device->y, device->setup );
    ba = sql.toUtf8();

    g_db.lock();

    do{
        res = g_db.query( ba.data() );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "update device failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }
    } while( 0 );

    g_db.unlock();

    if ( PEM_OK == res )
        res = __setup_device( device );

    return 	res;
}

pem_error_t db_thread::__setup_device( db_device_update* device )
{
     if ( DEV_ST_SETTING != device->setup )
         return PEM_OK;
}

/**
 *	load protocal from data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_load_protocal( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t		res	= PEM_OK;
    cls_res			sqlres;

    g_db.lock();

    do
    {
        res = g_db.query( "select serial, pto_name, pto_file, tunnel_type, dev_type, remark, used from tab_protocal order by serial asc" );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "load protocal failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = g_db.get_res( sqlres );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_ERR, "db thread", "get protocal result failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = __load_protocal( sqlres );
    }while( 0 );

    sqlres.free_res();

    g_db.unlock();

    return	res;
}

/**
 *	load protocal
 *
 * 	@sqlres			[in] the sql result object
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::__load_protocal( cls_res& sqlres )
{
    pem_s8_t		buf[8192];
    pem_s32_t		index		= 0;
    head_in&		head 		= *(head_in*)buf;
    ui_protocal*	protocal	= (ui_protocal*)(&head + 1);

    FILL_HEAD( head, MAIN_UI, UI_PROTOCAL, EN_NONE, 0 );

    while ( sqlres.get_next_row() )
    {
        index = 0;
        protocal->serial = sqlres.get_data_int( index++ );
        sqlres.get_data_string( index++, protocal->pto_name, sizeof(protocal->pto_name) );
        sqlres.get_data_string( index++, protocal->pto_file, sizeof(protocal->pto_file) );
        sqlres.get_data_string( index++, protocal->tunnel_type, sizeof(protocal->tunnel_type) );
        sqlres.get_data_string( index++, protocal->dev_type, sizeof(protocal->dev_type) );
        sqlres.get_data_string( index++, protocal->remark, sizeof(protocal->remark) );
        protocal->used	= sqlres.get_data_int( index++ );

        head.size 		+= sizeof(ui_protocal);
        protocal++;

        if ( (head.size + sizeof(head_in)) > (sizeof(buf) - sizeof(ui_protocal)) )
        {
            g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );
            head.size	= 0;
            protocal	= (ui_protocal*)(&head + 1);
        }
    }

    if ( head.size > 0 )
        g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );

    return	PEM_OK;
}

/**
 *	load alarm from data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_load_alarm( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t		res	= PEM_OK;
    cls_res			sqlres;

    g_db.lock();

    do
    {
        res = g_db.query( "select host, dev_id, cmp_start, alm_start, cmp_stop, alm_stop, link_host, link_dev from tab_alarm order by host asc" );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "load alarm failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = g_db.get_res( sqlres );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_ERR, "db thread", "get alarm result failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = __load_alarm( sqlres );
    }while( 0 );

    sqlres.free_res();

    g_db.unlock();

    return	res;
}

/**
 *	load alarm
 *
 * 	@sqlres			[in] the sql result object
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread ::__load_alarm( cls_res& sqlres )
{
    pem_s8_t		buf[8192];
    pem_s32_t		index;
    head_in&		head 		= *(head_in*)buf;
    ui_alarm*		alarm		= (ui_alarm*)(&head + 1);

    FILL_HEAD( head, MAIN_UI, UI_ALARM, EN_NONE, 0 );

    while ( sqlres.get_next_row() )
    {
        index = 0;
        sqlres.get_data_string( index++, alarm->host, sizeof(alarm->host) );
        sqlres.get_data_string( index++, alarm->dev_id, sizeof(alarm->dev_id) );
        sqlres.get_data_string( index++, alarm->cmp_start, sizeof(alarm->cmp_start) );
        alarm->alm_start	= sqlres.get_data_int( index++ );
        sqlres.get_data_string( index++, alarm->cmp_stop, sizeof(alarm->cmp_stop) );
        alarm->alm_stop		= sqlres.get_data_int( index++ );
        sqlres.get_data_string( index++, alarm->link_host, sizeof(alarm->link_host)  );
        sqlres.get_data_string( index++, alarm->link_dev, sizeof(alarm->link_dev)  );

        head.size 		+= sizeof(ui_alarm);
        alarm++;

        if ( (head.size + sizeof(head_in)) > (sizeof(buf) - sizeof(ui_alarm)) )
        {
            g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );
            head.size	= 0;
            alarm		= (ui_alarm*)(&head + 1);
        }
    }

    if ( head.size > 0 )
        g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );

    return	PEM_OK;
}

/**
 *	load event type from data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_load_event_type( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t		res	= PEM_OK;
    cls_res			sqlres;

    g_db.lock();

    do
    {
        res = g_db.query( "select serial, type from tab_event_type order by serial asc" );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "load event type failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = g_db.get_res( sqlres );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_ERR, "db thread", "get event type result failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = __load_event_type( sqlres );
    }while( 0 );

    sqlres.free_res();

    g_db.unlock();

    return	res;
}

/**
 *	load event type
 *
 * 	@sqlres			[in] the sql result object
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread ::__load_event_type( cls_res& sqlres )
{
    pem_s8_t			buf[8192];
    pem_s32_t			index;
    head_in&			head 		= *(head_in*)buf;
    ui_event_type*		event_type	= (ui_event_type*)(&head + 1);

    FILL_HEAD( head, MAIN_UI, UI_EVENT_TYPE, EN_NONE, 0 );

    while ( sqlres.get_next_row() )
    {
        index = 0;
        event_type->serial 		= sqlres.get_data_int( index++ );
        sqlres.get_data_string( index++, event_type->type, sizeof(event_type->type) );

        head.size 		+= sizeof(ui_event_type);
        event_type++;

        if ( (head.size + sizeof(head_in)) > (sizeof(buf) - sizeof(ui_event_type)) )
        {
            g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );
            head.size	= 0;
            event_type	= (ui_event_type*)(&head + 1);
        }
    }

    if ( head.size > 0 )
        g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );

    return	PEM_OK;
}

/**
 *	load event from data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_load_event( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t		res	= PEM_OK;
    cls_res			sqlres;

    g_db.lock();

    do
    {
        res = g_db.query( "select serial, type, datetime, user, descript from tab_event order by serial asc" );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "load event failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = g_db.get_res( sqlres );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_ERR, "db thread", "get event result failed[error = 0x%x, %s]", res, g_db.get_error() );
            break;
        }

        res = __load_event( sqlres );
    }while( 0 );

    sqlres.free_res();

    g_db.unlock();

    return	res;
}

/**
 *	load event
 *
 * 	@sqlres			[in] the sql result object
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread ::__load_event( cls_res& sqlres )
{
    pem_s8_t			buf[8192];
    pem_s32_t			index;
    head_in&			head 		= *(head_in*)buf;
    ui_event*			event	= (ui_event*)(&head + 1);

    FILL_HEAD( head, MAIN_UI, UI_EVENT, EN_NONE, 0 );

    while ( sqlres.get_next_row() )
    {
        index = 0;
        event->serial 		= sqlres.get_data_int( index++ );
        sqlres.get_data_string( index++, event->type, sizeof(event->type) );
        sqlres.get_data_string( index++, event->datetime, sizeof(event->datetime) );
        sqlres.get_data_string( index++, event->user, sizeof(event->user) );
        sqlres.get_data_string( index++, event->descript, sizeof(event->descript) );

        head.size += sizeof(ui_event);
        event++;

        if ( (head.size + sizeof(head_in)) > (sizeof(buf) - sizeof(ui_event)) )
        {
            g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );
            head.size	= 0;
            event		= (ui_event*)(&head + 1);
        }
    }

    if ( head.size > 0 )
        g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );

    return	PEM_OK;
}

/**
 *	load scene from data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_load_scene( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t		res	= PEM_OK;
    cls_res			sqlres;

    g_db.lock();

    do
    {
        res = g_db.query( "select serial, scene from tab_scene" );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "load scene failed[error = 0x%x]", res );
            break;
        }

        res = g_db.get_res( sqlres );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_ERR, "db thread", "get scene result failed[error = 0x%x]", res );
            break;
        }

        res = __load_scene( sqlres );
    }while( 0 );

    sqlres.free_res();

    g_db.unlock();

    return	res;
}

/**
 *	load scene
 *
 * 	@sqlres			[in] the sql result object
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::__load_scene( cls_res& sqlres )
{
    pem_s8_t			buf[8192];
    pem_s32_t			index;
    head_in&			head 		= *(head_in*)buf;
    ui_scene*			scene		= (ui_scene*)(&head + 1);

    FILL_HEAD( head, MAIN_UI, UI_SCENE, EN_NONE, 0 );

    while ( sqlres.get_next_row() )
    {
        index = 0;
        sqlres.get_data_int( index++ );
        sqlres.get_data_string( index++, scene->img, sizeof(scene->img) );

        head.size += sizeof(ui_scene);
        scene++;

        if ( (head.size + sizeof(head_in)) > (sizeof(buf) - sizeof(ui_scene)) )
        {
            g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );
            head.size	= 0;
            scene		= (ui_scene*)(&head + 1);
        }
    }

    if ( head.size > 0 )
        g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );

    return	PEM_OK;
}

/**
 *	save scene into data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_save_scene( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t		res			= PEM_OK;
    head_in&		head		= *(head_in*)pdata;
    db_scene_save*	save		= (db_scene_save*)(&head + 1);
    QString			strsql;
    QByteArray		ba;

    g_db.lock();
    do
    {
        strsql.sprintf( "update tab_scene set scene = \"%s\" where serial = 0", save->img );
        ba = strsql.toLatin1();
        res = g_db.query( ba.data() );
        if ( PEM_OK != res )
        {
            g_log.write( LOG_WARN, "db thread", "save scene failed[error = 0x%x]", res );
            break;
        }
    }while( 0 );
    g_db.unlock();

    if ( save->receipt )
        res = __update_scene( head, save );

    return	res;
}

/**
 *	update scene to ui
 *
 * 	@headdb			[in] the protocal head of db protocal
 * 	@save			[in] the pointer of db_scene_save
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::__update_scene( head_in& headdb, db_scene_save* save )
{
    pem_s8_t		buf[8192];
    head_in&		headui		= *(head_in*)buf;
    ui_scene_new*	scene_new	= (ui_scene_new*)(&headui + 1);

    FILL_HEAD( headui, MAIN_UI, UI_SCENE_NEW, headdb.entry, sizeof(ui_scene_new) );
    strncpy( scene_new->img, save->img, sizeof(scene_new->img) );

    if ( headui.size > 0 )
        g_tunnel.putdata( CL_UI, buf, headui.size + sizeof(head_in) );

    return 	PEM_OK;
}

/**
 *	load frame from data base
 *
 * 	@pdata			[in] the protocal buffer
 * 	@size			[in] the buffer size
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::_load_frame( pem_s8_t* pdata, pem_u32_t size )
{
    pem_error_t		res	= PEM_OK;
    cls_res			sqlres;

    g_db.lock();

    do
    {
        res = __load_frame( sqlres );
    } while( 0 );

    g_db.unlock();

    return res;
}

/**
 *	load frame
 *
 * 	@sqlres			[in] the sql result object
 *
 * 	return
 * 		==	PEM_OK		protocal is good
 * 		!=	PEM_OK		errorcode
 */
pem_error_t db_thread::__load_frame( cls_res& sqlres )
{
    pem_s8_t			buf[8192];
    head_in&			head 		= *(head_in*)buf;
    ui_frame*			frame		= (ui_frame*)(&head + 1);

    FILL_HEAD( head, MAIN_UI, UI_FRAME, EN_NONE, sizeof(ui_frame) );

    if ( head.size > 0 )
        g_tunnel.putdata( CL_UI, buf, head.size + sizeof(head_in) );

    return PEM_OK;
}
